home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 1
/
Nebula One.iso
/
Utilities
/
Workspace
/
AltDock
/
Source
/
IconView.m
< prev
next >
Wrap
Text File
|
1995-06-12
|
10KB
|
390 lines
/* IconView.m */
#import <objc/List.h>
#import <appkit/Bitmap.h>
#import <appkit/Listener.h>
#import <appkit/graphics.h>
#import <dpsclient/psops.h>
#import <dpsclient/wraps.h>
#import <strings.h>
#import <libc.h>
#import <math.h>
#import "MyApp.h"
#import "DockSpeaker.h"
#import "IconView.h"
#define UPPER_RIGHT 1
#define LOWER_RIGHT 2
@implementation IconView
+ new:(char *)name :icon :(int)xCoord :(int)yCoord
{
self = [super new];
/* copy the app's name */
appName = (char *)malloc(strlen(name) + 1);
strcpy(appName, name);
/* initialize bitmap locations */
bitmap = icon;
activeBitmap = [Bitmap findBitmapFor:"active"];
/* save location in dock grid */
xGridLocation = xCoord;
yGridLocation = yCoord;
/* figure out if we're the dock window */
if (!strcmp(appName, "Dock")) {
theDock = YES;
altDocAppHidden = NO;
}
/* initialize */
highLighted = NO;
active = NO;
appsPSContext = 0;
return self;
}
- initialize:list :(int)minX :(int)minY :(int)maxX :(int)maxY
/* give the dock the bounding box and list of all app windows */
{
xMin = minX;
xMax = maxX;
yMin = minY;
yMax = maxY;
windowList = list;
/* create the drawing order lists for moving diagonally */
upperRight = [self createOrderedListForCorner:UPPER_RIGHT];
lowerRight = [self createOrderedListForCorner:LOWER_RIGHT];
return self;
}
- createOrderedListForCorner:(int)corner
/* returns a list of windows ordered based on the corner parameter */
/* (this is the order in which they should be moved when moving toward */
/* this corner */
{
int i, x1, y1, x2, y2, j;
id list, tempList, iconWindow;
list = [List new];
tempList = [List new];
i = [windowList count];
/* insert all windows into the temporary list (ordered by x position) */
while (i--) {
iconWindow = [windowList objectAt:i];
[[iconWindow contentView] coordinates:&x1 :&y1];
j = 0;
while (j < [tempList count]) {
[[[tempList objectAt:j] contentView] coordinates:&x2 :&y2];
/* sort by x position */
if (corner == UPPER_RIGHT && x1 >= x2) {
break;
} else if (x1 >= x2) {
break;
}
j++;
}
if (j == [tempList count]) {
[tempList addObject:iconWindow];
} else if (![tempList insertObject:iconWindow at:j]) {
[tempList addObject:iconWindow];
}
}
i = [tempList count];
/* insert tempList windows into the final list, sorted by x and y */
while (i--) {
iconWindow = [tempList objectAt:i];
[[iconWindow contentView] coordinates:&x1 :&y1];
j = 0;
while (j < [list count]) {
[[[list objectAt:j] contentView] coordinates:&x2 :&y2];
/* sort by y */
if (corner == UPPER_RIGHT && x1 >= x2 && y1 >= y2) {
break;
} else if (x1 >= x2 && y1 <= y2) {
break;
}
j++;
}
if (j == [list count]) {
[list addObject:iconWindow];
} else if (![list insertObject:iconWindow at:j]) {
[list addObject:iconWindow];
}
}
[tempList free];
return list;
}
- drawSelf:(const NXRect *)rects :(int)rectCount
{
NXRect drawRect;
int numBitmaps;
NXPoint origin, activePoint;
/* initialize a drawing rectangle */
drawRect.origin.x = drawRect.origin.y = 0.0;
drawRect.size.width = drawRect.size.height = 64.0;
origin.x = origin.y = 8.0;
if (!theDock) {
/* if we're not the dock, draw our bezel */
NXDrawButton(&drawRect, 0);
NXInsetRect(&drawRect, 1.0, 1.0);
NXDrawButton(&drawRect, 0);
NXInsetRect(&drawRect, -1.0, -1.0);
/* draw our 48x48-bit icon */
[bitmap composite:NX_SOVER toPoint:&origin];
activePoint.x = 64.0 - 2.0 - 18.0;
activePoint.y = drawRect.origin.y + 4.0;
/* draw the three dots if our program isn't active */
if (!active) {
[activeBitmap composite:NX_COPY toPoint:&activePoint];
}
/* highlight ourself if we're getting our app to run or unhide */
if (highLighted) {
NXInsetRect(&drawRect, 2.0, 2.0);
NXHighlightRect(&drawRect);
}
} else {
/* we're the dock so just copy our 64x64-bit icon into ourself */
origin.x = origin.y = 0.0;
[bitmap composite:NX_COPY toPoint:&origin];
}
return self;
}
#define MOVEMASK (NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK)
- mouseDown:(NXEvent *)theEvent
{
NXPoint mouseDownLocation;
NXEvent *currentEvent;
NXCoord oldX, oldY, newX, newY, dx, dy, x, y;
NXRect frameRect;
int windowNum;
/* if we're not the dock, see if we should unhide our application */
if (!theDock) {
[self handleNonDock:theEvent];
return self;
}
/* hide or unhide the dock's menus and icon window if a double click */
if (theEvent->data.mouse.click == 2) {
[self hideOrUnhide];
}
[window addToEventMask:MOVEMASK];
/* get the dock window's location */
[window getFrame:&frameRect];
/* convert the mouse's location to global (screen) coordinates */
mouseDownLocation = theEvent->location;
PScurrenttoscreen(mouseDownLocation.x, mouseDownLocation.y, &oldX, &oldY);
/* initialization */
newX = frameRect.origin.x;
newY = frameRect.origin.y;
currentEvent = [NXApp getNextEvent:MOVEMASK];
while (currentEvent->type != NX_MOUSEUP) {
/* things get messed up if we move our window and ask the window */
/* to convert our mouse location to screen coordinates, so we */
/* use this call instead to get the mouse's screen location */
PScurrentmouse(0, &x, &y);
/* offset from previous mouse location */
dx = x - oldX;
dy = y - oldY;
/* compute the dock window's proposed origin */
newX = dx + frameRect.origin.x;
newY = dy + frameRect.origin.y;
/* make sure this is ok (and fix it if not) */
[self checkCoords:&newX :&newY];
/* move everyone the correct amount */
[self moveWindows:(newX - frameRect.origin.x)
:(newY - frameRect.origin.y)];
/* get our new origin and save the current mouse location */
[window getFrame:&frameRect];
oldX = x;
oldY = y;
/* wait for another mouse event */
currentEvent = [NXApp getNextEvent:MOVEMASK];
}
/* impose the NeXT dock's grid behaviour on the window positions */
[self snapToGrid:&newX :&newY];
[self moveWindows:(newX - frameRect.origin.x)
:(newY - frameRect.origin.y)];
return self;
}
- checkCoords:(float *)x :(float *)y
/* constrain the dock window's location based on the bounding box */
{
float maxX, maxY;
if (*x < 4) *x = 4;
if (*y < 0) *y = 0;
maxX = (xMax - xMin) * 64.0 + 4.0;
maxY = (yMax - yMin) * 64.0;
if (*y > maxY) *y = maxY;
if (*x > maxX) *x = maxX;
return self;
}
- snapToGrid:(float *)x :(float *)y
/* make sure windows lay on 64-bit boundaries */
{
*x = rint((*x - 4) / 64.0) * 64.0 + 4.0;
*y = rint(*y / 64.0) * 64.0;
return self;
}
- moveWindows:(float)dx :(float)dy
/* move the windows dx and dy */
{
int numberOfWindows, startX, stopX, startY, stopY, i;
id theList, moveWindow;
NXRect frameRect;
BOOL reverse;
/* note that when moving to upper left, we can use the lower right */
/* window list, just traverse it in the opposite direction */
if (dx <= 0 && dy < 0) {
theList = upperRight;
reverse = YES;
} else if (dx >= 0 && dy > 0) {
theList = upperRight;
reverse = NO;
} else if (dx < 0 && dy >= 0) {
theList = lowerRight;
reverse = YES;
} else { /* (dx > 0 && dy <= 0) */
theList = lowerRight;
reverse = NO;
}
numberOfWindows = [theList count];
if (!reverse) {
i = 0;
while (i < numberOfWindows) {
moveWindow = [theList objectAt:i++];
[moveWindow getFrame:&frameRect];
[moveWindow moveTo:(frameRect.origin.x + dx)
:(frameRect.origin.y + dy)];
}
} else {
i = numberOfWindows;
while (i--) {
moveWindow = [theList objectAt:i];
[moveWindow getFrame:&frameRect];
[moveWindow moveTo:(frameRect.origin.x + dx)
:(frameRect.origin.y + dy)];
}
}
return self;
}
- handleNonDock:(NXEvent *)theEvent
/* click in a non-dock window */
{
port_t appPort;
int flag;
/* only concern ourselves with double clicks */
if (theEvent->data.mouse.click == 2) {
/* simulate NeXT dock functionality */
highLighted = YES;
[self display];
[NXApp deactivateSelf];
/* get the WorkSpace to make sure our app is running */
appPort = NXPortFromName((rindex(appName, '/') + 1), NULL);
if (appPort == PORT_NULL) {
/* something went wrong */
highLighted = NO;
[self display];
[NXApp activateSelf:YES];
return self;
}
/* now unhide the app (just like the WorkSpace) */
[[NXApp appSpeaker] setSendPort:appPort];
[[NXApp appSpeaker] unhide];
/* save our app's PostScript context (for a later version, maybe) */
appsPSContext = [NXApp activeApp];
/* all done, so show app is active and unhighlight ourselves */
highLighted = NO;
active = YES;
[self display];
}
return self;
}
- hideOrUnhide
/* hide or unhide the dock app's menu */
{
if (altDocAppHidden) {
[[NXApp mainMenu] orderFront:self];
altDocAppHidden = NO;
} else {
[[NXApp mainMenu] orderOut:self];
altDocAppHidden = YES;
}
return self;
}
- (BOOL)theDock
{
return theDock;
}
- coordinates:(int *)xCoord :(int *)yCoord
/* return our grid coordinates */
{
*xCoord = xGridLocation;
*yCoord = yGridLocation;
return self;
}
@end